package com.dcivision.workflow.core;

import java.sql.Connection;
import java.util.Iterator;
import java.util.List;

import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.ApplicationMessageList;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.Utility;
import com.dcivision.workflow.bean.MtmWorkflowStepUserActor;
import com.dcivision.workflow.bean.WorkflowStep;
import com.dcivision.workflow.dao.WorkflowStepDAObject;

/**
 * 
 * @author tc.tang 2007-02-03
 *
 */
public class WorkflowStepOperationWarningMessageManager {

  SessionContainer sessionContainer = null;
  Connection conn = null;
  
  public WorkflowStepOperationWarningMessageManager(SessionContainer sessionContainer,Connection conn){
    this.sessionContainer = sessionContainer;
    this.conn = conn;
  }
  
  public ApplicationMessageList createWorkflowStepWarningMessage(WorkflowStep step,String operationType) throws ApplicationException{
    if(GlobalConstant.OP_MODE_INSERT.equals(operationType)){
      return createWorkflowStepInsertWarningMessage(step);
    }else if(GlobalConstant.OP_MODE_UPDATE.equals(operationType)){
      return createWorkflowStepUpdateWarningMessage(step);
    }else if(GlobalConstant.OP_MODE_DELETE.equals(operationType)){
      return createWorkflowStepDeleteWarningMessage(step);
    }else{
      return null;
    }
  }
  
  public ApplicationMessageList createWorkflowStepInsertWarningMessage(WorkflowStep step) throws ApplicationException{
    ApplicationMessageList warningList = new ApplicationMessageList();
    //create the assign step warning info
    warningList.addMessages(createAssignAtRunTimeWarningMessage(step));
    //create the step if this route to any assign at runTime step
    warningList.addMessages(createRouteToCurrentStepWarningMessage(step));
    return warningList;
  }
  public ApplicationMessageList createWorkflowStepUpdateWarningMessage(WorkflowStep step) throws ApplicationException{
    ApplicationMessageList warningList = new ApplicationMessageList();
    //create the assign step warning info
    warningList.addMessages(createAssignAtRunTimeWarningMessage(step));
    //create the step if this route to any assign at runTime step
    warningList.addMessages(createRouteToCurrentStepWarningMessage(step));
    return warningList;
  }
  
  public ApplicationMessageList createWorkflowStepDeleteWarningMessage(WorkflowStep step){
    ApplicationMessageList warningList = new ApplicationMessageList();
    warningList.addMessage("workflow.message.workflowStep_delete_loopbackStep_connect_to_endStep", step.getStepName());
    return warningList;
  }
  
  public ApplicationMessageList createAllWorkflowStepWarningMessage(Integer workflowRecordID,String operationType) throws ApplicationException{
    ApplicationMessageList warningList = new ApplicationMessageList();
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(this.sessionContainer,this.conn);
    List stepList = stepDAO.getListByWorkflowRecordIDAndActorType(workflowRecordID,MtmWorkflowStepUserActor.ACTOR_TYPE_RUNTIME_ASSIGN);
    for(Iterator it=stepList.iterator();it.hasNext();){
      WorkflowStep step = (WorkflowStep)it.next();
      warningList.addMessages(createAssignAtRunTimeWarningMessage(step));
    }
    return warningList;
  }
  
  public ApplicationMessageList createAllWorkflowStepWarningMessage(Integer workflowRecordID) throws ApplicationException{
    return createAllWorkflowStepWarningMessage(workflowRecordID,GlobalConstant.OP_MODE_UPDATE);
  }
  
  private ApplicationMessageList createAssignAtRunTimeWarningMessage(WorkflowStep step) throws ApplicationException{
    ApplicationMessageList warningMessageList = new ApplicationMessageList();
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(this.sessionContainer,this.conn);
    //0.if this step is allow assign at runtime
    if(!MtmWorkflowStepUserActor.ACTOR_TYPE_RUNTIME_ASSIGN.equals(step.getAssignActorType())){//assign at run time
      return null;
    }
    //1.if parentStep have due-date and no_response_action is treat as complete
    List parentStepList=stepDAO.getListByChildStepID(step.getID());
    for(Iterator it=parentStepList.iterator();it.hasNext();){
      WorkflowStep tmpParentStep = (WorkflowStep)it.next();
      if(WorkflowStep.NO_RESPONSE_ACTION_COMPLETE.equals(tmpParentStep.getOnNoResponseAction())){
        warningMessageList.addMessage("workflow.message.workflowStep_assign_at_runtime_conflict_for_autoComplete",new Object[]{tmpParentStep.getStepName(),step.getStepName()});
      }
    }
    //2.if any step noresponseAction is route to this step
    warningMessageList.addMessages(createAnyStepRouteToCurrentAssignStepWarningMessage(step));
    return warningMessageList;
  }
  
  
  private ApplicationMessageList createRouteToCurrentStepWarningMessage(WorkflowStep step) throws ApplicationException{
    ApplicationMessageList warningMessageList = new ApplicationMessageList();
    //0.if this step have due-date
    //1.if this step noResponseAction is route to other step
    if(Utility.isEmpty(step.getOnNoResponseNextStepID())){
      return null;
    }
    //2.the target step is allow assign at runtime
    warningMessageList.addMessages(createCurrentStepRouteAnyAssignStepWarningMessage(step));
    
    return warningMessageList;
  }
  
  private ApplicationMessageList createAnyStepRouteToAnyAssignStepWarningMessage(Integer workflowRecordID) throws ApplicationException{
    ApplicationMessageList warningList = new ApplicationMessageList();
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(this.sessionContainer,this.conn);
    List stepList = stepDAO.getListByWorkflowRecordID(workflowRecordID);
    for(Iterator it=stepList.iterator();it.hasNext();){
      WorkflowStep step = (WorkflowStep)it.next();
      warningList.addMessages(createRouteToCurrentStepWarningMessage(step));
    }
    return warningList;
  }
  
  private ApplicationMessageList createCurrentStepRouteAnyAssignStepWarningMessage(WorkflowStep currentStep) throws ApplicationException{
    ApplicationMessageList warningList = new ApplicationMessageList();
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(this.sessionContainer,this.conn);
    List stepList = stepDAO.getListByWorkflowRecordIDAndActorType(currentStep.getWorkflowRecordID(),MtmWorkflowStepUserActor.ACTOR_TYPE_RUNTIME_ASSIGN);
    for(Iterator it=stepList.iterator();it.hasNext();){
      WorkflowStep assignStep = (WorkflowStep)it.next();
      warningList.addMessages(createCurrentStepRouteToAssignAtRunTimeWarningMessage(currentStep,assignStep));
    }
    return warningList;
  }
  private ApplicationMessageList createAnyStepRouteToCurrentAssignStepWarningMessage(WorkflowStep currentAssignStep) throws ApplicationException{
    ApplicationMessageList warningList = new ApplicationMessageList();
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(this.sessionContainer,this.conn);
    List stepList = stepDAO.getListByWorkflowRecordID(currentAssignStep.getWorkflowRecordID());
    for(Iterator it=stepList.iterator();it.hasNext();){
      WorkflowStep step = (WorkflowStep)it.next();
      warningList.addMessages(createCurrentStepRouteToAssignAtRunTimeWarningMessage(step,currentAssignStep));
    }
    return warningList;
  }
  
  private ApplicationMessageList createCurrentStepRouteToAssignAtRunTimeWarningMessage(WorkflowStep currentStep,WorkflowStep assignStep){
    ApplicationMessageList warningList = new ApplicationMessageList();
    //0.assign step is assign at runTime
    if(!MtmWorkflowStepUserActor.ACTOR_TYPE_RUNTIME_ASSIGN.equals(assignStep.getAssignActorType())){//assign at run time
      return null;
    }
    //1.current to is route to this assign step
    if(assignStep.getID().equals(currentStep.getOnNoResponseNextStepID())){
      warningList.addMessage("workflow.message.workflowStep_assign_at_runtime_conflict_for_routeOtherStep",new Object[]{currentStep.getStepName(),assignStep.getStepName()});
    }
    
    return warningList;
  }
}
